<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.8.0 -->
<title>0064: Cairo VIII – Animation on a DrawingArea | gtkDcoding</title>
<meta name="generator" content="Jekyll v4.3.4" />
<meta property="og:title" content="0064: Cairo VIII – Animation on a DrawingArea" />
<meta name="author" content="Ron Tarrant" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="GTK Tutorial on animating with Cairo." />
<meta property="og:description" content="GTK Tutorial on animating with Cairo." />
<link rel="canonical" href="http://localhost:4000/posts/0064-cairo-vii-drawingarea-animation.html" />
<meta property="og:url" content="http://localhost:4000/posts/0064-cairo-vii-drawingarea-animation.html" />
<meta property="og:site_name" content="gtkDcoding" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2019-08-23T00:00:00-04:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="0064: Cairo VIII – Animation on a DrawingArea" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Ron Tarrant"},"dateModified":"2019-08-23T00:00:00-04:00","datePublished":"2019-08-23T00:00:00-04:00","description":"GTK Tutorial on animating with Cairo.","headline":"0064: Cairo VIII – Animation on a DrawingArea","mainEntityOfPage":{"@type":"WebPage","@id":"http://localhost:4000/posts/0064-cairo-vii-drawingarea-animation.html"},"url":"http://localhost:4000/posts/0064-cairo-vii-drawingarea-animation.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="stylesheet" href="../assets/main.css">
  <link rel="stylesheet" href="../css/style.css" /><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="gtkDcoding" /></head>
<body><header class="site-header" role="banner">

  <div class="wrapper"><a class="site-title" rel="author" href="../">gtkDcoding</a><nav class="site-nav">
        <input type="checkbox" id="nav-trigger" class="nav-trigger" />
        <label for="nav-trigger">
          <span class="menu-icon">
            <svg viewBox="0 0 18 15" width="18px" height="15px">
              <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
            </svg>
          </span>
        </label>

        <div class="trigger"><a class="page-link" href="../about.html">About</a><a class="page-link" href="../index-reverse.html">Posts in Date Order</a><a class="page-link" href="../topics.html">Blog Posts by Topic</a></div>
      </nav></div>
</header>
<main class="page-content" aria-label="Content">
      <div class="wrapper">
        <article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
	<header class="post-header">
		<link rel="stylesheet" href="../css/font_size.css" />
		<link rel="stylesheet" href="../css/figure.css" />
		<link rel="stylesheet" href="../css/topics/cairo.css" />  <!-- sub in the tag/topic -->
		<link rel="stylesheet" href="../css/modal.css" />
		<link rel="stylesheet" href="../css/post.css" />
		<link rel="stylesheet" href="../css/mascot_effects.css" />

		
		
		<p class="post-meta">
		<time class="dt-published" datetime="2019-08-23T00:00:00-04:00" itemprop="datePublished">Friday, August 23, 2019
		</time>• by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">Ron Tarrant</span></span></p>
	</header>

	<div class="post-content e-content" itemprop="articleBody">
		<div class="skew-line"></div>
		<h1 id="0064-cairo-viii--animation-on-a-drawingarea">0064: Cairo VIII – Animation on a DrawingArea</h1>

<p>When animating on a <code class="language-plaintext highlighter-rouge">DrawingArea</code>, the drawing is done more or less the same way, but a bit at a time over a number of frames. Also, a signal is hooked up to a callback in the normal way, and then in the callback, a <code class="language-plaintext highlighter-rouge">Timeout</code> object is created. It’s the <code class="language-plaintext highlighter-rouge">Timeout</code> object, as you may guess, that’s used to determine how often the Surface gets refreshed and that’s what sets the frame rate.</p>

<h2 id="a-simple-animated-timer">A Simple Animated Timer</h2>

<!-- 0, 1 -->
<!-- first occurrence of application and terminal screenshots on a single page -->
<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img0" src="../images/screenshots/018_cairo/cairo_24.gif" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal0" class="modal">																	<!-- modal# -->
				<span class="close0">&times;</span>															<!-- close# -->
				<img class="modal-content" id="img00" />															<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal0");														// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img0");															// img#
			var modalImg = document.getElementById("img00");													// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close0")[0];											// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img1" src="../images/screenshots/018_cairo/cairo_24_term.png" alt="Current example terminal output" />		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal1" class="modal">																				<!-- modal# -->
				<span class="close1">&times;</span>																		<!-- close# -->
				<img class="modal-content" id="img11" />																		<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal1");																	// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img1");																		// img#
			var modalImg = document.getElementById("img11");																// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close1")[0];														// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																								<!-- ------------- filename (below) --------- -->
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/018_cairo/cairo_24_counter_animation.d" target="_blank">here</a>.
	</div>
</div>
<!-- end of snippet for first (1st) occurrence of application and terminal screenshots on a single page -->

<p>In this first example, we’ll slap down the numbers 1 through 24 in sequence and refresh the <code class="language-plaintext highlighter-rouge">DrawingArea</code>’s <code class="language-plaintext highlighter-rouge">Surface</code> every 24th of a second.</p>

<p>Here’s the initialization section of the <code class="language-plaintext highlighter-rouge">MyDrawingArea</code> object:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Timeout</span> <span class="n">_timeout</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">number</span> <span class="p">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">fps</span> <span class="p">=</span> <span class="mi">1000</span> <span class="p">/</span> <span class="mi">24</span><span class="p">;</span> <span class="c1">// 24 frames per second</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">Timeout</code> class is part of <code class="language-plaintext highlighter-rouge">glib</code>, so it’s imported with:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="n">glib</span><span class="p">.</span><span class="n">Timeout</span><span class="p">;</span>
</code></pre></div></div>

<p>at the top of the file.</p>

<p>And the <code class="language-plaintext highlighter-rouge">fps</code> variable is an easy way to set the frames per second. Timing is in milliseconds, so 1000 (one second’s worth of milliseconds) divided by the desired frame rate gives you exactly what you expect:</p>

<ul>
  <li>1000 / 24 = 24 fps,</li>
  <li>1000 / 30 = 30 fps,</li>
  <li>1000 / 6 = 6 fps, and</li>
  <li>so on.</li>
</ul>

<p>Setting up the <code class="language-plaintext highlighter-rouge">Timeout</code> is the first thing you do in the callback and it’s done like this:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="n">_timeout</span> <span class="k">is</span> <span class="kc">null</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">_timeout</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Timeout</span><span class="p">(</span><span class="n">fps</span><span class="p">,</span> <span class="p">&amp;</span><span class="n">onFrameElapsed</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">Timeout</code> object acts very much like a signal hook up. In our example, once the <code class="language-plaintext highlighter-rouge">Timeout</code> is instantiated:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">onFrameElasped()</code> function acts like a callback,</li>
  <li><code class="language-plaintext highlighter-rouge">fps</code> tells the <code class="language-plaintext highlighter-rouge">Timeout</code> how often to call <code class="language-plaintext highlighter-rouge">onFrameElapsed()</code>, and</li>
  <li><code class="language-plaintext highlighter-rouge">false</code> tells the <code class="language-plaintext highlighter-rouge">Timeout</code> not to fire right away, but to wait for the first interval to pass first.</li>
</ul>

<p>And here’s what <code class="language-plaintext highlighter-rouge">Timeout</code>’s “callback” looks like:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">onFrameElapsed</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">GtkAllocation</span> <span class="n">size</span><span class="p">;</span>
	<span class="n">getAllocation</span><span class="p">(</span><span class="n">size</span><span class="p">);</span>
		
	<span class="n">queueDrawArea</span><span class="p">(</span><span class="n">size</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="n">size</span><span class="p">.</span><span class="n">y</span><span class="p">,</span> <span class="n">size</span><span class="p">.</span><span class="n">width</span><span class="p">,</span> <span class="n">size</span><span class="p">.</span><span class="n">height</span><span class="p">);</span>
		
	<span class="k">return</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
	
<span class="p">}</span> <span class="c1">// onFrameElapsed()</span>
</code></pre></div></div>

<p>We grab a <code class="language-plaintext highlighter-rouge">GtkAllocation</code> like we have before so we can get the dimensions of the <code class="language-plaintext highlighter-rouge">DrawingArea</code>, then use those dimensions to redraw. We could, if we wanted, refresh only a small portion of the <code class="language-plaintext highlighter-rouge">DrawingArea</code>, but we’ll talk more about that another time.</p>

<p>As for the actual drawing itself, we do this:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="n">number</span> <span class="p">&gt;</span> <span class="mi">24</span><span class="p">)</span> <span class="c1">// number range: 1 - 24</span>
<span class="p">{</span>
	<span class="n">number</span> <span class="p">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">context</span><span class="p">.</span><span class="n">showText</span><span class="p">(</span><span class="n">number</span><span class="p">.</span><span class="n">to</span><span class="p">!</span><span class="nb">string</span><span class="p">());</span>
<span class="n">number</span><span class="p">++;</span>
</code></pre></div></div>

<p>And that’s in the <code class="language-plaintext highlighter-rouge">onDraw</code> callback… which is the real callback attached to the <code class="language-plaintext highlighter-rouge">DrawingArea</code> as opposed to the sort-of callback attached to the <code class="language-plaintext highlighter-rouge">Timeout</code>.</p>

<p>We don’t have to set up a <code class="language-plaintext highlighter-rouge">for()</code> loop because the <code class="language-plaintext highlighter-rouge">Timeout</code> repeats 24 times per second and ends up doing the job a loop would normally do.</p>

<h2 id="animating-the-drawing-of-a-circle">Animating the Drawing of a Circle</h2>

<!-- 2, 3 -->
<!-- second occurrence of application and terminal screenshots on a single page -->
<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img2" src="../images/screenshots/018_cairo/cairo_25.gif" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal2" class="modal">																<!-- modal# -->
				<span class="close2">&times;</span>														<!-- close# -->
				<img class="modal-content" id="img22" />														<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal2");													// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img2");														// img#
			var modalImg = document.getElementById("img22");												// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close2")[0];										// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img3" src="../images/screenshots/018_cairo/cairo_25_term.png" alt="Current example terminal output" /> 		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal3" class="modal">																			<!-- modal# -->
				<span class="close3">&times;</span>																	<!-- close# -->
				<img class="modal-content" id="img33" />																	<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal3");																// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img3");																	// img#
			var modalImg = document.getElementById("img33");															// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close3")[0];													// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																							<!--------- filename (below) ------------>
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/018_cairo/cairo_25_draw_circle_animation.d" target="_blank">here</a>.
	</div>
</div>
<!-- end of snippet for second (2nd) occurrence of application and terminal screenshots on a single page -->

<p>This example is very similar to redrawing text. In the initialization section we have:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Timeout</span> <span class="n">_timeout</span><span class="p">;</span>
<span class="kt">float</span> <span class="n">arcLength</span> <span class="p">=</span> <span class="n">PI</span> <span class="p">/</span> <span class="mi">12</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">fps</span> <span class="p">=</span> <span class="mi">1000</span> <span class="p">/</span> <span class="mi">12</span><span class="p">;</span> <span class="c1">// 12 frames per second</span>
</code></pre></div></div>

<p>This time, we’re running at 12 frames per second. The length of arc we’ll draw each frame is <code class="language-plaintext highlighter-rouge">PI / 12</code> and because we’re working in radians and a full circle is <code class="language-plaintext highlighter-rouge">2PI</code>, that means our circle will be redrawn once every two seconds.</p>

<p>The <code class="language-plaintext highlighter-rouge">onFrameElapsed()</code> <code class="language-plaintext highlighter-rouge">Timeout</code> callback is the same as before, so let’s have a gander at the <code class="language-plaintext highlighter-rouge">onDraw</code> callback:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">onDraw</span><span class="p">(</span><span class="n">Scoped</span><span class="p">!</span><span class="n">Context</span> <span class="n">context</span><span class="p">,</span> <span class="n">Widget</span> <span class="n">w</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">if</span><span class="p">(</span><span class="n">_timeout</span> <span class="k">is</span> <span class="kc">null</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">_timeout</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Timeout</span><span class="p">(</span><span class="n">fps</span><span class="p">,</span> <span class="p">&amp;</span><span class="n">onFrameElapsed</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
		
	<span class="p">}</span>
	
	<span class="k">if</span><span class="p">(</span><span class="n">arcLength</span> <span class="p">&gt;</span> <span class="p">(</span><span class="n">PI</span> <span class="p">*</span> <span class="mi">2</span><span class="p">))</span>
	<span class="p">{</span>
		<span class="n">arcLength</span> <span class="p">=</span> <span class="n">PI</span> <span class="p">/</span> <span class="mi">12</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="n">arcLength</span> <span class="p">+=</span> <span class="p">(</span><span class="n">PI</span> <span class="p">/</span> <span class="mi">12</span><span class="p">);</span>

	<span class="n">context</span><span class="p">.</span><span class="n">setLineWidth</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
	<span class="n">context</span><span class="p">.</span><span class="n">arc</span><span class="p">(</span><span class="mi">320</span><span class="p">,</span> <span class="mi">180</span><span class="p">,</span> <span class="mi">40</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">arcLength</span><span class="p">);</span>
	<span class="n">context</span><span class="p">.</span><span class="n">stroke</span><span class="p">();</span> <span class="c1">// and draw</span>
	
	<span class="k">return</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
	
<span class="p">}</span> <span class="c1">// onDraw()</span>
</code></pre></div></div>

<p>The action starts with the <code class="language-plaintext highlighter-rouge">if()</code> statement when we measure out a length of arc to draw, then add it to the length of arc we already have. Then we set up the line width, set up the <code class="language-plaintext highlighter-rouge">arc()</code> function and do the stroke.</p>

<p>Pretty simple. And, of course, you could do any other drawing in there as well. And this not being the 80’s or 90’s, you’d have to pack in a very long list of drawing commands before you slow down the refresh rate.</p>

<h2 id="flipbook-animation">Flipbook Animation</h2>

<!-- 4, 5 -->
<!-- third occurrence of application and terminal screenshots on a single page -->
<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img4" src="../images/screenshots/018_cairo/cairo_26.gif" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal4" class="modal">																<!-- modal# -->
				<span class="close4">&times;</span>														<!-- close# -->
				<img class="modal-content" id="img44" />														<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal4");													// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img4");														// img#
			var modalImg = document.getElementById("img44");												// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close4")[0];										// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img5" src="../images/screenshots/018_cairo/cairo_26_term.png" alt="Current example terminal output" /> 		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal5" class="modal">																			<!-- modal# -->
				<span class="close5">&times;</span>																	<!-- close# -->
				<img class="modal-content" id="img55" />																	<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal5");																// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img5");																	// img#
			var modalImg = document.getElementById("img55");															// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close5")[0];													// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																							<!---------- filename (below) ---------->
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/018_cairo/cairo_26_flipbook_animation.d" target="_blank">here</a>.
	</div>
</div>
<!-- end of snippet for third (3rd) occurrence of application and terminal screen shots on a single page -->

<p>And now for the <em>pièce de resistance</em>, loading a bunch of frames and flipping through them at 12 fps… which simulates shooting on twos. That’s animator parlance meaning that each image is shot twice and played back at 24 fps. Anyway, here’s the initialization section:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">currentFrame</span> <span class="p">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">fps</span> <span class="p">=</span> <span class="mi">1000</span> <span class="p">/</span> <span class="mi">12</span><span class="p">;</span> <span class="c1">// 6 frames per second</span>
<span class="n">Timeout</span> <span class="n">_timeout</span><span class="p">;</span>
<span class="n">Pixbuf</span><span class="p">[]</span> <span class="n">pixbufs</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">numberOfFrames</span> <span class="p">=</span> <span class="mi">75</span><span class="p">;</span>
</code></pre></div></div>

<p>This time around, we’re going to keep track of our current frame. And there’s also an array of <code class="language-plaintext highlighter-rouge">Pixbuf</code>s to store all the individual images that will be our frames.</p>

<p>The constructor plays a bigger part in things this time:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">this</span><span class="p">()</span>
<span class="p">{</span>
	<span class="k">foreach</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">;</span> <span class="mf">0.</span><span class="p">.</span><span class="n">numberOfFrames</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="k">if</span><span class="p">(</span><span class="n">i</span> <span class="p">&lt;</span> <span class="mi">10</span><span class="p">)</span>
		<span class="p">{</span>
			<span class="n">pixbufs</span> <span class="p">~=</span> <span class="k">new</span> <span class="n">Pixbuf</span><span class="p">(</span><span class="s">"./images/sequence/one00"</span> <span class="p">~</span> <span class="n">i</span><span class="p">.</span><span class="n">to</span><span class="p">!</span><span class="nb">string</span><span class="p">()</span> <span class="p">~</span> <span class="s">".tif"</span><span class="p">);</span>
		<span class="p">}</span>
		<span class="k">else</span>
		<span class="p">{</span>
			<span class="n">pixbufs</span> <span class="p">~=</span> <span class="k">new</span> <span class="n">Pixbuf</span><span class="p">(</span><span class="s">"./images/sequence/one0"</span> <span class="p">~</span> <span class="n">i</span><span class="p">.</span><span class="n">to</span><span class="p">!</span><span class="nb">string</span><span class="p">()</span> <span class="p">~</span> <span class="s">".tif"</span><span class="p">);</span>
		<span class="p">}</span>

	<span class="p">}</span> <span class="c1">// for()</span>
		
	<span class="n">addOnDraw</span><span class="p">(&amp;</span><span class="n">onDraw</span><span class="p">);</span>
		
<span class="p">}</span> <span class="c1">// this()</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">foreach()</code> loop loads all the frames and inside that, we build the file names through string concatenation (which is less trouble than copying and pasting a whole big long list of file names into an array).</p>

<p>Once the files are all loaded snug into their <code class="language-plaintext highlighter-rouge">Pixbuf</code>s, we hook up the signal and move on.</p>

<p>Again, the <code class="language-plaintext highlighter-rouge">Timeout</code>’s callback is the same, so here’s the <code class="language-plaintext highlighter-rouge">onDraw</code> callback:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">onDraw</span><span class="p">(</span><span class="n">Scoped</span><span class="p">!</span><span class="n">Context</span> <span class="n">context</span><span class="p">,</span> <span class="n">Widget</span> <span class="n">w</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">if</span><span class="p">(</span><span class="n">_timeout</span> <span class="k">is</span> <span class="kc">null</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">_timeout</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Timeout</span><span class="p">(</span><span class="n">fps</span><span class="p">,</span> <span class="p">&amp;</span><span class="n">onFrameElapsed</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
			
	<span class="p">}</span>
		
	<span class="n">context</span><span class="p">.</span><span class="n">setSourcePixbuf</span><span class="p">(</span><span class="n">pixbufs</span><span class="p">[</span><span class="n">currentFrame</span><span class="p">],</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
	<span class="n">context</span><span class="p">.</span><span class="n">paint</span><span class="p">();</span>
		
	<span class="n">currentFrame</span> <span class="p">+=</span> <span class="mi">1</span><span class="p">;</span>
		
	<span class="k">if</span><span class="p">(</span><span class="n">currentFrame</span> <span class="p">&gt;=</span> <span class="n">numberOfFrames</span><span class="p">)</span>
	<span class="p">{</span>
		<span class="n">currentFrame</span> <span class="p">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span>
		
	<span class="k">return</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
		
<span class="p">}</span> <span class="c1">// onDraw()</span>
</code></pre></div></div>

<p>So here we:</p>

<ul>
  <li>instantiate and hook up the <code class="language-plaintext highlighter-rouge">Timeout</code>,</li>
  <li>grab a frame from our array and stuff it into the Context, and</li>
  <li>do some frame number math.</li>
</ul>

<p>Nothing to it.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Next time we’ll… dive back into the MVC series and look at the <code class="language-plaintext highlighter-rouge">TreeStore</code> to see how it differs from the <code class="language-plaintext highlighter-rouge">ListStore</code>. Don’t miss it, eh.</p>

<div class="blog-nav">
	<div style="float: left;">
		<a href="./0063-cairo-vii-draw-save-images.html">Previous: Cairo Draw &amp; Save Images</a>
	</div>
	<div style="float: right;">
		<a href="./0065-mvc-x-treestore-basics.html">Next: MVC - TreeStore Basics</a>
	</div>
</div>
<p>
	<h3></h3>
<div class="inpage-frame">
	<a href="https://github.com/sponsors/rontarrant">
		<BR>
		<BR>
		<B>Is this article useful? Educational? Entertaining, perhaps?</B>
		<BR>
		<figure class="left">
			<img src="../images/favorite_32.png" alt="Sponsorship heart" style="width: 32px; height: 32px;">
		</figure>
		You're free to accept or decline this invitation to become our newest sponsor.
	</a>
</div>
	<h4 class="comment-blurb"><B>Comments? Questions? Observations?</B></h4>
	<p>
		Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
	</p>
	<script src="https://utteranc.es/client.js"
		repo="rontarrant"
		issue-term="pathname"
		theme="github-light"
		crossorigin="anonymous"
		async>
	</script>
	<ul>
		<li> come on over to the <a href="https://forum.dlang.org/">D Language Forum</a> and look for one of the <i>gtkDcoding</i> announcement posts, </li>
		<li> drop by <a href="https://forum.gtkd.org/">the <i>GtkD Forum</i></a>,</li>
		<li> follow the link below to email me, or</li>
		<li> go to the	<a href="https://www.facebook.com">gtkDcoding Facebook page.</a></li>
	</ul>
</p>
<p> You can also subscribe <a href="/feed.xml">via RSS</a> so you won't miss anything. Thank you very much for dropping by.</p>
<p>&copy; Copyright 2025 Ron Tarrant </p>
</div>

	<a class="u-url" href="./0064-cairo-vii-drawingarea-animation.html" hidden></a>
</article>

      </div>
    </main><footer class="site-footer h-card">
  <data class="u-url" href="/"></data>

  <div class="wrapper">

    <h2 class="footer-heading">gtkDcoding</h2>

    <div class="footer-col-wrapper">
      <div class="footer-col footer-col-1">
        <ul class="contact-list">
          <li class="p-name">Ron Tarrant</li><li><a class="u-email" href="mailto:gtkDcoding@gmail.com">gtkDcoding@gmail.com</a></li></ul>
      </div>

      <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/rontarrant"><svg class="svg-icon"><use xlink:href="../assets/minima-social-icons.svg#github"></use></svg> <span class="username">rontarrant</span></a></li></ul>
</div>

      <div class="footer-col footer-col-3">
        <p>Simple examples of how to use GtkD to build GUI applications.</p>
      </div>
    </div>

  </div>

</footer>
</body>

</html>
